package org.sxp.common.validator;

import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sxp.common.exception.ParamException;
import org.sxp.common.validator.group.AddGroup;
import org.sxp.common.validator.group.UpdateGroup;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.lang.reflect.Type;
import java.util.*;

/**
 * @author shenxingping
 * @date 2021/12/29
 */
public class ParamValidatorAOP {
    private Logger log = LoggerFactory.getLogger(ParamValidatorAOP.class);
    private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
    static Map<Type, Object> basicTypeMap = new HashMap();

    public ParamValidatorAOP() {
    }

    public void doBefore(JoinPoint jp) throws ParamException {
        this.validateParam(jp.getArgs());
    }

    public void doBeforeL1(JoinPoint jp) throws ParamException {
        this.validateParam(jp.getArgs(), AddGroup.class);
    }

    public void doBeforeL2(JoinPoint jp) throws ParamException {
        this.validateParam(jp.getArgs(), UpdateGroup.class);
    }

//    public void doBeforeL3(JoinPoint jp) throws ParamException {
//        this.validateParam(jp.getArgs(), L3.class);
//    }
//
//    public void doBeforeL4(JoinPoint jp) throws ParamException {
//        this.validateParam(jp.getArgs(), L4.class);
//    }

    private <T> void validateParam(T args, Class... groups) throws ParamException {
        if (args != null) {
            this.log.debug("args.class=" + args.getClass());
            if (args.getClass().isArray()) {
                Object[] objs = (Object[])((Object[])args);
                Object[] var5 = objs;
                int var6 = objs.length;

                for(int var7 = 0; var7 < var6; ++var7) {
                    Object obj = var5[var7];

                    Class clz;
                    try {
                        clz = obj.getClass();
                    } catch (Exception var14) {
                        continue;
                    }

                    this.log.debug("clz=" + clz + ";isBasicType=" + this.isBasicType(clz) + ";isArray=" + clz.isArray() + ";isList=" + List.class.isAssignableFrom(clz) + ";isMap=" + Map.class.isAssignableFrom(clz));
                    if (!this.isBasicType(clz)) {
                        Iterator it;
                        if (List.class.isAssignableFrom(clz)) {
                            List list = (List)obj;
                            it = list.iterator();

                            while(it.hasNext()) {
                                Object o = it.next();
                                this.validate(o, groups);
                            }
                        } else if (Map.class.isAssignableFrom(clz)) {
                            Map map = (Map)obj;
                            it = map.values().iterator();

                            while(it.hasNext()) {
                                this.validate(it.next(), groups);
                            }
                        } else if (clz.isArray()) {
                            if (this.isBasicType(clz.getComponentType())) {
                                return;
                            }

                            Object[] os = (Object[])((Object[])obj);
                            Object[] var10 = os;
                            int var11 = os.length;

                            for(int var12 = 0; var12 < var11; ++var12) {
                                Object o = var10[var12];
                                this.validate(o, groups);
                            }
                        } else {
                            this.validate(obj, groups);
                        }
                    }
                }
            }

        }
    }

    private <T> void validate(T obj, Class... groups) throws ParamException {
        if (!this.isBasicType(obj.getClass())) {
            Set<ConstraintViolation<T>> violationSet = this.validator.validate(obj, groups);
            if (!violationSet.isEmpty()) {
                StringBuffer sb = new StringBuffer();
                Iterator var5 = violationSet.iterator();

                while(var5.hasNext()) {
                    ConstraintViolation<T> model = (ConstraintViolation)var5.next();
                    sb.append(model.getMessage() + " | ");
                }

                this.log.error("[HDF]parameter validate Exception：" + sb.toString());
                throw new ParamException("[HDF]参数校验异常：" + sb.toString());
            }
        }
    }

    private boolean isBasicType(Class typeClass) {
        if (typeClass.isPrimitive()) {
            return true;
        } else {
            return basicTypeMap.containsKey(typeClass);
        }
    }

    static {
        basicTypeMap.put(String.class, (Object)null);
        basicTypeMap.put(Number.class, (Object)null);
        basicTypeMap.put(Boolean.class, (Object)null);
        basicTypeMap.put(Character.class, (Object)null);
        basicTypeMap.put(Byte.class, (Object)null);
        basicTypeMap.put(Short.class, (Object)null);
        basicTypeMap.put(Integer.class, (Object)null);
        basicTypeMap.put(Long.class, (Object)null);
        basicTypeMap.put(Float.class, (Object)null);
        basicTypeMap.put(Double.class, (Object)null);
    }
}
